#include "StdAfx.h"
#include "util.h"

/* compute cross product (convenience function) */
void normal( float n[], float v0[], float v1[], float v2[] ) {
	float d0[3] = {v1[0]-v0[0], v1[1]-v0[1], v1[2]-v0[2]};
	float d1[3] = {v2[0]-v1[0], v2[1]-v1[1], v2[2]-v1[2]};
	n[0] = d0[1]*d1[2] - d0[2]*d1[1];
	n[1] = d0[2]*d1[0] - d0[0]*d1[2];
	n[2] = d0[0]*d1[1] - d0[1]*d1[0];
}

void drawPoint(float x, float y, float z) {
	glBegin(GL_POINTS);
	glVertex3f(x, y, z);
	glEnd();
}

void drawCircle(float radius, float x, float y)
{
	glBegin(GL_POLYGON);

	for (int i=0; i < 360; i++)
	{
		float degInRad = i*DEG2RAD;
		glVertex2f(cos(degInRad)*radius + x,sin(degInRad)*radius + y);
	}

	glEnd();
}
void drawWedge(float radius, int degrees, float x, float y)
{
	glBegin(GL_POLYGON);

	for (int i=0; i < degrees; i++)
	{
		float degInRad = i*DEG2RAD;
		glVertex2f(cos(degInRad)*radius + x,sin(degInRad)*radius + y);
	}
	glVertex2f(x, y);

	glEnd();
}

// http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
int pnpoly(int npol, float *xp, float *yp, float x, float y) {
	int i, j, c = 0;
	for (i = 0, j = npol-1; i < npol; j = i++) {
		if ((((yp[i]<=y) && (y<yp[j])) ||
			((yp[j]<=y) && (y<yp[i]))) &&
			(x < (xp[j] - xp[i]) * (y - yp[i]) / (yp[j] - yp[i]) + xp[i]))

			c = !c;
	}
	return c;
}

void printBitmapString(const char* s) {
	if (s && strlen(s)) {
		while (*s) {
			glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, *s);
			s++;
		}
	}
}

// http://www.dei.isep.ipp.pt/~matos/cadeiras/2004-05/cgra/docs/manual/glutStrokeCharacter.3GLUT.html
void printString(float x, float y, char* s) {
	char *p;

	//glShadeModel(GL_FLAT);
	//glDisable (GL_DEPTH_TEST);
	//	disable();
	glColor3f (1.0, 1.0, 0.0);

	glPushMatrix();
	//glScalef(1,1,1);
	//glTranslatef(-1100,0,0);
	glLineWidth(10.0);

	//	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	//glEnable(GL_BLEND);
	//glEnable(GL_LINE_SMOOTH);
	//glLineWidth(2.0);

	// glPushMatrix();
	glTranslatef(0.f, 0.f, 0);

	//glScalef(20.f, 20.f, 20.f);

	
	for (p = s; *p; p++) {
		glutStrokeCharacter(GLUT_STROKE_MONO_ROMAN, *p);
	}
	glPopMatrix();
}


GLuint loadTextureRAW( const char * filename, int wrap )
{
  GLuint texture;
  int width, height;
  BYTE * data;
  FILE * file;

  // open texture data
  file = fopen( filename, "rb" );
  if ( file == NULL ) return 0;

  // allocate buffer
  width = 256;
  height = 256;
  data = (BYTE *)malloc( width * height * 3 );

  // read texture data
  fread( data, width * height * 3, 1, file );
  fclose( file );

  // allocate a texture name
  glGenTextures( 1, &texture );

  // select our current texture
  glBindTexture( GL_TEXTURE_2D, texture );

  // select modulate to mix texture with color for shading
  glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );

  // when texture area is small, bilinear filter the closest MIP map
  glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
                   GL_LINEAR_MIPMAP_NEAREST );
  // when texture area is large, bilinear filter the first MIP map
  glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );

  // if wrap is true, the texture wraps over at the edges (repeat)
  //       ... false, the texture ends at the edges (clamp)
  glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
                   wrap ? GL_REPEAT : GL_CLAMP );
  glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
                   wrap ? GL_REPEAT : GL_CLAMP );

  // build our texture MIP maps
  gluBuild2DMipmaps( GL_TEXTURE_2D, 3, width,
    height, GL_RGB, GL_UNSIGNED_BYTE, data );

  // free buffer
  free( data );

  return texture;

}

GLuint loadTexturePNG( const char * filename, int wrap )
{
	GLuint texture;

	pngInfo info;
	// Load PNG and set orientation to OpenGL default
	pngSetStandardOrientation(true);
	texture = pngBind(filename, PNG_NOMIPMAP, PNG_ALPHA, &info, GL_CLAMP, GL_NEAREST, GL_NEAREST);
	
	if (texture != 0) {
	   puts("Loaded Texture.png with resounding success");
	   printf("Size=%i,%i Depth=%i Alpha=%i\n", info.Width, info.Height, info.Depth, info.Alpha);
	}
	else {
	   puts("Can't load Texture.png");
	   exit(1);
	}

	return texture;

}

// Renders a png file into the frame buffer
void renderPNG(const char * filename, float x, float y) {
	pngRawInfo info;
	int result = NULL;

	// Read PNG
	pngSetStandardOrientation(true);
	result = pngLoadRaw(filename, &info);

	if (result == 0) {
		printf("ERROR: Could not load PNG\n");
	} else {
		// Set position for rastering
		glRasterPos2f(x,y);

		// raster!
		glEnable(GL_BLEND);
		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
		glDrawPixels(info.Width, info.Height, GL_RGBA, GL_UNSIGNED_BYTE, info.Data);
		glDisable(GL_BLEND);

		// Free memory
		free(info.Data);
		free(info.Palette);
	}

}
